/*
 * CS_REG_BUY_ITEM_RESULT.cpp
 *
 *  Created on: 2013. 5. 28.
 *      Author: the2
 */

#include "../../Command.h"

#include "../Engine/Validator/Command.h"
#include "../Engine/Validator/Session.h"
#include "../Engine/Validator/Static.h"

#include "../../User.h"
#include "../../NResource/Static.h"

#include "../../NLogic/Static.h"
#include "../../NLogic/Function.h"
#include "../../NLogic/MailBox.h"
#include "../../NLogic/VirtualCurrency.h"

#include "../../NProcess/Static.h"
#include "../../NProcess/KakaoSender.h"
#include "../../NProcess/ReceiptChecker.h"

#include "../../NState/Static.h"


namespace ProjectZ { namespace NCommand {

void SendFailBuyItemResult(User * pUser, int res, int errorCode)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(res);
	*pAck << errorCode;
	*pAck << pUser->GetVirtualCurrency()->GetZen();
	pAck->MakePacket(CMD_SC_REG_BUY_ITEM_RESULT);

	pUser->Send(pAck);
}

void Command::CS_REG_BUY_ITEM_RESULT(User * pUser, ::Network::Packet * pPacket)
{
/*	ZNO_CS_REG_BUY_ITEM_RESULT				0x230E
	{
		u8	u8market_type;					// 0 : Google Android, 1 : App Store
		u8	u8is_gift;						// 0 : 일반 구매, 1 : 젠선물하기
		u8	u8tid;
		u32	u32buy_seq;
		u32 u32friend_gid;					// u8is_gift 가 0 이 아닐때 유효, 선물 받게될 친구 gid
		u8	u8result;
		u32	u32err_code;
		u32 u32sub_err_code;
		str	strorder_id;
		str	strpurchase_data;
		str	strsignature;
	}

	ZNO_SC_REG_BUY_ITEM_RESULT				0x230F
	{
		s16	s16ack;
		u32	u32err_code;
		u32 u32current_zen;
	}*/

	PREPARE_PACKET;

	uint8_t marketType		= 0;
	uint8_t isGift			= 0;
	uint8_t tid				= 0;
	uint32_t buySeq			= 0;
	uint32_t recvUserSeq	= 0;
	uint8_t result			= 0;
	uint32_t errCode		= 0;
	uint32_t subErrCode		= 0;

	Toolkit::Str<80>	orderID;
	Toolkit::Str<4096>	purchase;
	Toolkit::Str<4096>	signature;

	*pPacket >> marketType;
	*pPacket >> isGift;
	*pPacket >> tid;
	*pPacket >> buySeq;
	*pPacket >> recvUserSeq;
	*pPacket >> result;
	*pPacket >> errCode;
	*pPacket >> subErrCode;
	*pPacket >> orderID;
	*pPacket >> purchase;
	*pPacket >> signature;

	PROCESSLOG("CS_REG_BUY_ITEM_RESULT : userSeq=%d, charSeq=%d, market=%d, gift=%d, tid=%d, buySeq=%d, recvUserSeq=%d, "
			"result=%d, errorCode=%d, subErrorCode=%d, orderid=%s, purchase=(%s), signature=(%s)",
			pUser->GetUserSeq(), pUser->GetCharacterInfo().characterseq,
			marketType, isGift, tid, buySeq, recvUserSeq, result, errCode,
			subErrCode, orderID.c_str(), purchase.c_str(), signature.c_str());

	// 데이터 유효성 검사
	if (buySeq < 0 || result < 0 || result > 1)
	{
		PROCESSLOG("CS_REG_BUY_ITEM_RESULT : buySeq < 0 || result < 0 || result > 1");
		SendFailBuyItemResult(pUser, ACK_UNKNOWN_ERROR, errCode);
		return;
	}

	if (marketType < 0 || marketType > 2)
	{
		PROCESSLOG("CS_REG_BUY_ITEM_RESULT : INVALID MARKETTYPE=%d", marketType);
		SendFailBuyItemResult(pUser, ACK_UNKNOWN_ERROR, errCode);
		return;
	}

	// 상태 확인
	{
		::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
		clsAuto->SetQueryType(::Database::Command::SELECT);
		clsAuto->MakeQuery("select status from buyitemdata where seq = %d", buySeq);

		if (false == ::Database::GETSESSION()->SyncExecute(1, clsAuto))
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : false == ::Database::GETSESSION()->SyncExecute(1, clsAuto)");
			return;
		}

		if( clsAuto->GetErrorIdx() != 0 )
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : clsAuto->GetErrorIdx() != 0");
			return;
		}

		int status = 0;

		while (clsAuto->Next())
		{
			clsAuto->GetRecord() >> status;
		}

		if (static_cast<int>(REQUESTING) != status)
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : INVALID STATUS!! userseq=%d", pUser->GetUserSeq());
			SendFailBuyItemResult(pUser, ACK_OK, errCode);
			return;
		}
	}



	// START V2
	NProcess::ReceiptChecker::Param clsParam;
	clsParam._buySeq			= buySeq;
	clsParam._errorCode			= errCode;
	clsParam._isGift			= isGift;
	clsParam._marketType		= marketType;
	clsParam._orderID			= orderID.c_str();
	clsParam._purchase			= purchase.c_str();
	clsParam._signature			= signature.c_str();
	clsParam._recvUserSeq		= recvUserSeq;
	clsParam._result			= result;
	clsParam._subErrorCode		= subErrCode;
	clsParam._tid				= tid;
	clsParam._user				= pUser;

//	pUser->IncreaseRefCount();
	pUser->SetState(NState::Static::InstancePtr()->RECEIPTCHECKSTATE());

	NProcess::Static::InstancePtr()->GetReceiptChecker().Push(clsParam);
	// END   V2











#if 0
	int status = FAIL;
	int curl_status = RECEIPT_FAIL;
	int validator_status = RECEIPT_FAIL;

	if (result)
	{
		// 영수증 확인
		::Validator::Command *pCommand = ::Validator::GETCOMMANDPOOL()->NEW();

		if (marketType == 0)	// Google
		{
			DEBUGLOG("CS_REG_BUY_ITEM_RESULT : marketType Google");
			pCommand->SetType(::Validator::Command::E_Type::GOOGLE);
			pCommand->SetPurchaseData(purchase.c_str());
			pCommand->SetSignature(signature.c_str());

			::Validator::GETSESSION()->SyncExecute(pCommand);

			validator_status = pCommand->GetStatus();
			curl_status = pCommand->GetResult();

			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : CURL_RESULT=%d, VALIDATOR_RESULT=%d", curl_status, validator_status);

//			if (1 == curl_status && 0 == validator_status && (0 == errCode || 7 == errCode) )
			if (1 == curl_status && 0 == validator_status)
			{
				status = SUCCESS;		// 성공
			}
			else
			{
				status = RECEIPT_FAIL;	// 실패
			}

			::Validator::GETCOMMANDPOOL()->DEL(pCommand);
		}
		else if (marketType == 1)	// IOS
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : marketType IOS");
			pCommand->SetType(::Validator::Command::E_Type::IOS);
			pCommand->SetReceiptData(const_cast<char*>(purchase.c_str()));

			::Validator::GETSESSION()->SyncExecute(pCommand);

			validator_status = pCommand->GetStatus();
			curl_status = pCommand->GetResult();

			// SandBox 계정인 경우 SandBox서버에 확인 요청
			if (0 == curl_status && 21007 == validator_status)
			{
				PROCESSLOG("CS_REG_BUY_ITEM_RESULT : marketType IOS_TEST");
				pCommand->SetType(::Validator::Command::E_Type::IOS_TEST);
				pCommand->SetReceiptData(const_cast<char*>(purchase.c_str()));

				::Validator::GETSESSION()->SyncExecute(pCommand);

				validator_status = pCommand->GetStatus();
				curl_status = pCommand->GetResult();
			}

			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : CURL_RESULT=%d, VALIDATOR_RESULT=%d", curl_status, validator_status);

			if (0 == curl_status && 0 == validator_status)
			{
				status = SUCCESS;		// 성공
			}
			else
			{
				status = RECEIPT_FAIL;	// 실패
			}

			::Validator::GETCOMMANDPOOL()->DEL(pCommand);
		}
		else if (marketType == 2)	// Emulator
		{
			if (true == ::ProjectZ::Config::Instance().GetResourceDatabase()._isTest)
				status = SUCCESS;
		}
	}

	// 아이템 구매 상태 갱신
	{
		::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
		clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
		clsAuto->MakeQuery("call sp_update_BuyItemData(%d,'%s',%d,%d)", recvUserSeq, orderID.c_str(), status, buySeq);

		if (false == ::Database::GETSESSION()->SyncExecute(1, clsAuto))
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : false == ::Database::GETSESSION()->SyncExecute(1, clsAuto)");
			return;
		}

		if( clsAuto->GetErrorIdx() != 0 )
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : clsAuto->GetErrorIdx() != 0");
			return;
		}
	}

	// 아이템 구매 실패 히스토리 저장
	if (status != SUCCESS)
	{
		PROCESSLOG("CS_REG_BUY_ITEM_RESULT : status is not SUCCESS!! (%d)", status);

		SendFailBuyItemResult(pUser, ACK_RECEIPT_FAILE, validator_status);

		::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
		clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
		clsAuto->MakeQuery("call sp_insert_BuyItemFailData(%d,%d,%d,%d,%d)",
				errCode, subErrCode, buySeq, curl_status, validator_status);

		if (false == ::Database::GETSESSION()->SyncExecute(1, clsAuto))
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : false == ::Database::GETSESSION()->SyncExecute");
			return;
		}

		if( clsAuto->GetErrorIdx() != 0 )
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : clsAuto->GetErrorIdx() != 0");
			return;
		}

		return;
	}

	NResource::ProductData::Flyweight * pFly = NResource::Static::InstancePtr()->GetProductResource()->GetFly(pUser, tid);
	if (NULL == pFly)
	{
		PROCESSLOG("CS_REG_BUY_ITEM_RESULT : pFly is NULL!!");
		return;
	}

	// 젠 선물
	if (1 == isGift)
	{
		NLogic::MailBox::Mail::Data clsMailData;
		clsMailData.send_user_seq		= pUser->GetUserInfo().userseq;
		clsMailData.send_user_nickname	= pUser->GetUserInfo().nickname.c_str();
		clsMailData.send_user_imageurl	= pUser->GetUserInfo().profile_url.c_str();
		clsMailData.recv_user_seq		= recvUserSeq;
		clsMailData.message				= NResource::Static::InstancePtr()->GetMailMessageResource()->GetMessageGiftZen();
		clsMailData.zen					= pFly->_DEFAULT_AMOUNT + pFly->_BONUS_AMOUNT;
		clsMailData.gift_vcindex		= pFly->_GIFT_VC_INDEX;
		clsMailData.gift_status			= EM_GIFT_ZEN;

		if (false == NLogic::NFunction::SendMail(pUser, clsMailData))
		{
			PROCESSLOG("CS_REG_BUY_ITEM_RESULT : false == NLogic::NFunction::SendMail");
			return;
		}
	}
	else
	{
		// VC 히스토리 저장
		DEBUGLOG("CS_REG_BUY_ITEM_RESULT : tid=%d, vcIndex=%d", tid, pFly->_VC_INDEX);
		NLogic::NFunction::VCProcess(pUser, pFly->_VC_INDEX, pFly->_DEFAULT_AMOUNT + pFly->_BONUS_AMOUNT);
	}

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << validator_status;
	*pAck << pUser->GetVirtualCurrency()->GetZen();
	pAck->MakePacket(CMD_SC_REG_BUY_ITEM_RESULT);
	pUser->Send(pAck);


	// Kakao로 과금 정보 전송
	if (marketType == 0 || marketType == 1)
	{
		NProcess::KakaoSender::Param clsParam;
		clsParam._socialID	= pUser->GetSocialID().c_str();
		clsParam._company	= pUser->GetCompany();
		clsParam._nPrice	= pFly->_PRICE;
		clsParam._buySeq	= buySeq;

		NProcess::Static::InstancePtr()->GetKakaoSender().Push(clsParam);
	}
#endif
}

} /*NCommand*/ } /*ProjectZ*/
